package br.ufpe.cin.mac.middleware.connectors.concrete;

import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import br.ufpe.cin.mac.middleware.connectors.ConcreteConnector;
import br.ufpe.cin.mac.util.ConnectionPackage;
import br.ufpe.cin.mac.util.Constants;
import br.ufpe.cin.mac.util.Message;

/**
 * Class HttpServer
 * 
 * @author Osmany
 * @author Rafael Roque
 *
 */
public class HttpServer extends ConcreteConnector implements HttpServerMBean {

//	private final int PORT = 80;

	private ServerSocket serverSocket;

	private Map<String, ConnectionPackage> connections;

	long seq;

	String type;

	public HttpServer() {
		super(HttpServer.class.getCanonicalName());
		this.connections = Collections
				.synchronizedMap(new HashMap<String, ConnectionPackage>());
	}

	public void connect() {
		try {
			serverSocket = new ServerSocket(Constants.HTTP_PORT);
			System.err.println("HttpServer running");
		} catch (Exception e) {
			e.printStackTrace();
		}
		while (serverSocket.isBound()) {
			try {
				final Socket socket = serverSocket.accept();
				new Thread() {
					public void run() {
						receive(socket);
					}
				}.start();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public void disconnect(Socket socket) throws Exception {
		// TODO Auto-generated method stub
	}

	/***************************************************************************
	 * ******************** ********************* ****************** PORTS
	 * ***************** * ******************************************
	 */

	public void invC(Message msg) {
		System.err.println("HttpS: Recebido pelo invC");
		this.buffer.put(msg.hashCode(), msg);

		sendNotification(msg.hashCode(), "invS");
	}

	public Message invS(int hashMsg) {
		System.err.println("HttpS: Retirado pelo invS");
		return (Message) this.buffer.remove(hashMsg);
	}

	public Message terC(int hashMsg) {
		System.err.println("HttpS: Retirado pelo terC");
		try {
			final Message msg = this.buffer.remove(hashMsg);
			new Thread() {
				public void run() {
					send(msg);
				}
			}.start();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public void terS(Message msg) {
		System.err.println("HttpS: Recebido pelo terS");
		this.buffer.put(msg.hashCode(), msg);

		sendNotification(msg.hashCode(), "terC");
	}

	/* EXPERIMENTAL */

	private void receive(Socket socket) {
		try {
			ObjectInputStream in = new ObjectInputStream(socket
					.getInputStream());
			Message msg = (Message) in.readObject();
			ConnectionPackage pack = new ConnectionPackage(socket);
			pack.setIn(in);
			this.connections.put(msg.getSender(), pack);
			this.invC(msg);

			while (socket.isConnected()) {
				msg = (Message)in.readObject();
				this.invC(msg);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void send(Message msg) {
		String client = msg.getSender();
		ConnectionPackage pack = connections.get(client);
		synchronized (pack) {
			ObjectOutputStream out = pack.getOut();
			connections.put(client, pack);
			try {
				out.writeObject(msg);
				out.flush();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}


	@Override
	protected void msgManager(Message msg) {
		// TODO Auto-generated method stub

	}
	
	@Override
	public void setHost(String host) {
		// TODO Auto-generated method stub
		
	}
}
